package run.iget.admin.quartz.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import run.iget.admin.quartz.config.QuartzProperties;
import run.iget.admin.quartz.entity.ScheduleJobEntity;
import run.iget.admin.quartz.enums.ScheduleStatusEnum;
import run.iget.admin.quartz.mapper.ScheduleJobMapper;
import run.iget.admin.quartz.req.ScheduleJobReq;
import run.iget.admin.quartz.service.ScheduleJobService;
import run.iget.admin.quartz.utils.ScheduleUtils;
import run.iget.framework.common.req.PageReq;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Objects;

/**
 * 定时任务
 *
 * @author 阿沐 babamu@126.com
 */
@Service
@AllArgsConstructor
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobMapper, ScheduleJobEntity>
        implements ScheduleJobService {

    private final Scheduler scheduler;
    private final QuartzProperties properties;

    /**
     * 启动项目时，初始化定时器
     */
    @PostConstruct
    public void init() throws SchedulerException {
        if (properties.notEnabled()) {
            return;
        }
        scheduler.clear();
        List<ScheduleJobEntity> scheduleJobList = super.list();
        for (ScheduleJobEntity scheduleJob : scheduleJobList) {
            ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
        }
    }


    @Override
    public boolean saveOrUpdate(ScheduleJobEntity entity) {
        boolean flag = false;
        if (Objects.nonNull(entity.getId())) {
            flag = updateById(entity);
            // 更新定时任务
            if (flag) {
                ScheduleJobEntity scheduleJob = getById(entity.getId());
                ScheduleUtils.updateSchedulerJob(scheduler, scheduleJob);
            }
        } else {
            entity.setStatus(ScheduleStatusEnum.PAUSE.getValue());
            flag = super.save(entity);
            if (flag) {
                ScheduleUtils.createScheduleJob(scheduler, entity);
            }
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> idList) {
        if (CollUtil.isEmpty(idList)) {
            return;
        }
        for (Long id : idList) {
            ScheduleJobEntity scheduleJob = getById(id);
            // 删除定时任务
            if (removeById(id)) {
                ScheduleUtils.deleteScheduleJob(scheduler, scheduleJob);
            }
        }
    }

    @Override
    public void run(ScheduleJobEntity vo) {
        ScheduleJobEntity scheduleJob = getById(vo.getId());
        if (scheduleJob == null) {
            return;
        }

        ScheduleUtils.run(scheduler, scheduleJob);
    }

    @Override
    public void changeStatus(ScheduleJobEntity vo) {
        ScheduleJobEntity scheduleJob = getById(vo.getId());
        if (scheduleJob == null) {
            return;
        }

        // 更新数据
        scheduleJob.setStatus(vo.getStatus());
        updateById(scheduleJob);

        if (ScheduleStatusEnum.PAUSE.getValue() == vo.getStatus()) {
            ScheduleUtils.pauseJob(scheduler, scheduleJob);
        } else if (ScheduleStatusEnum.NORMAL.getValue() == vo.getStatus()) {
            ScheduleUtils.resumeJob(scheduler, scheduleJob);
        }
    }

    @Override
    public Page<ScheduleJobEntity> list(PageReq<ScheduleJobReq> query) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .orderBy(ScheduleJobEntity::getId).desc();
        if (Objects.nonNull(query.getQueryBean())) {
            queryWrapper.where(ScheduleJobEntity::getJobName).like(query.getQueryBean().getJobName())
                    .and(ScheduleJobEntity::getJobGroup).like(query.getQueryBean().getJobGroup())
                    .and(ScheduleJobEntity::getStatus).eq(query.getQueryBean().getStatus())
                    .and(ScheduleJobEntity::getCreateTime).ge(query.getQueryBean().getStartTime())
                    .and(ScheduleJobEntity::getCreateTime).le(query.getQueryBean().getEndTime());
        }
        return super.page(query.getPage(), queryWrapper);
    }

}
